Skip to content

fix(swiftpm): persist --config-command so the in-build sync keeps using it - #57756

Closed
chrfalch wants to merge 2 commits into
mainfrom
chrfalch/spm-persist-config-command
Closed

fix(swiftpm): persist --config-command so the in-build sync keeps using it#57756
chrfalch wants to merge 2 commits into
mainfrom
chrfalch/spm-persist-config-command

Conversation

@chrfalch

Copy link
Copy Markdown
Collaborator

Summary:

spm add --config-command worked once, then broke every build.

An app that replaces @react-native-community/cli autolinking — an Expo app, for instance — has to override the autolinking config command, which --config-command (and RCT_SPM_AUTOLINKING_CONFIG_COMMAND) exists to do. But the flag was never stored anywhere. So:

  1. npx react-native spm add --config-command '[...]' → succeeds, writes a valid project ✅
  2. Build in Xcode → the "Sync SPM Autolinking" phase re-derives autolinking.json, doesn't know about the flag, falls back to the default command, and fails ❌
PhaseScriptExecution failed with a nonzero exit code
  → Sync SPM Autolinking
  → 'npx --no-install @react-native-community/cli config' exited with status 1

The only real workaround was exporting RCT_SPM_AUTOLINKING_CONFIG_COMMAND into Xcode's environment — i.e. committing it to .xcode.env — which shouldn't be necessary when you already passed a flag. Reported by the Expo team while testing SwiftPM.

Fix: pin the command into the .spm-injected.json marker at add/update time, and read it back on later runs — the same set-or-preserve pin the neighbouring artifactsVersionOverride already uses.

Resolution order, unchanged at the front and only extended at the back:

--config-command  →  RCT_SPM_AUTOLINKING_CONFIG_COMMAND  →  pinned value  →  default

Both input routes persist. The help text advertises the env var as an equivalent way to supply the command, so pinning only the flag would have left half the documented interface broken in exactly the same way — export the env var, run spm add, and the build phase (which does not inherit your shell) still fails. The pin therefore stores the resolved command from either route.

Two subtleties worth a reviewer's eye:

  • generateAutolinkingConfig resolves the env var internally when no explicit command is passed, so handing it the pin would silently outrank a developer's env override. The read path therefore withholds the pin while the env var is set, letting the existing precedence do its job. The four order cases are tested, including that a whitespace-only env var falls through to the pin rather than stranding it.
  • A pinned value is re-validated through the same parseConfigCommandJson the flag goes through, so a hand-edited or corrupt marker degrades to the env/default command instead of injecting a bogus argv into a build.

Because this is now persistent state, add/update logs one line when the command comes from the pin, naming .spm-injected.json — a stale pin should be diagnosable from build output rather than invisible. There is no "clear" verb short of deinit, same as the version pin; that is noted in the marker comment.

122 added lines across three source files. No new mechanism, no changes to the sync scripts, and nothing baked into the generated build phase.

Noticed while here, filed separately, deliberately not fixed: readArtifactsVersionOverride — the version pin this is modelled on — has no production caller. Only its write half is wired, and two comments claim the build-time sync reads it. Those comments are corrected here (they misled me while writing this); wiring the version pin up is its own change.

This isn't blocking anyone

Expo's SwiftPM verification is not blocked on this, so it needn't be rushed. The env-var half of the override already works at build time: adding

export RCT_SPM_AUTOLINKING_CONFIG_COMMAND='["node","…/expo-modules-autolinking.js","react-native-config","--json","--platform","ios"]'

to the app's .xcode.env (or .xcode.env.local) gets the command into the sync phase, because the generated phase sources both files before dispatching. That is what unblocks Expo today, and it is exactly the "commit an env var to .xcode.env" step this PR removes the need for.

One caveat that argues for fixing it properly rather than documenting the workaround: the phase sources .xcode.env only when NODE_BINARY is unset (nodeAndRnDirPreamble). An app that sets NODE_BINARY as an Xcode build setting — a documented RN practice — never sources those files, so the workaround silently does nothing there and the build fails with no hint as to why. Persisting the flag doesn't depend on any of that plumbing.

Changelog:

[Internal] [Fixed] - SwiftPM: persist spm --config-command so the in-build autolinking sync keeps using it

Test Plan:

yarn jest packages/react-native/scripts31 suites, 703 tests (25 new).

Each new test written red first, covering:

  • the command round-trips through .spm-injected.json (marker content asserted)
  • addupdate without the flag keeps the pin; a later flag overwrites it
  • add with only the env var set pins the env-derived command, and a later run with neither flag nor env resolves it back
  • all four resolution-order cases, including that the env var beats the pin, and that a whitespace-only env var pins nothing and falls through
  • an invalid non-blank env var still fails loud rather than pinning garbage
  • a corrupt or hand-edited pin (bare string, [], non-string member, empty-string member, object) degrades to the default rather than throwing
  • deinit drops it with the marker

Not covered: no test drives a real sync end to end, since that needs artifacts, codegen and a real pbxproj. The two halves are tested separately against the same marker field — the injector writes configCommand, and the resolver reads it. The original failure was reported from a real Expo app build; confirmation that this fixes that build is still pending on the Expo side.

`spm add --config-command '<argv>'` succeeded and wrote a valid project, then
every subsequent Xcode build failed: the injected "Sync SPM Autolinking" phase
re-derives autolinking.json on each build, had no knowledge of the flag, and
fell back to `npx --no-install @react-native-community/cli config` — which an
app that replaces CLI autolinking (an Expo app, say) does not have. A
successful `spm add` therefore produced an unbuildable project. Reported by the
Expo team while verifying SwiftPM.

Pin the command into the `.spm-injected.json` marker at add/update time and read
it back on later runs, mirroring the neighbouring `artifactsVersionOverride`
set-or-preserve pin. Resolution order is unchanged at the front and only
extended at the back:

    --config-command -> RCT_SPM_AUTOLINKING_CONFIG_COMMAND -> pin -> default

Both input routes persist. The help text advertises the env var as an
equivalent way to supply the command, so pinning only the flag would have left
half the documented interface broken the same way; the pin stores the resolved
command from either route.

Two details worth knowing:

- generateAutolinkingConfig resolves the env var internally when no explicit
  command is passed, so handing it the pin would silently outrank a developer's
  env override. The read path withholds the pin while the env var is set and
  lets the existing precedence apply. A whitespace-only env var pins nothing and
  falls through, using the same blankness predicate as the resolver so the two
  cannot drift.
- A pinned value is re-validated through the same parseConfigCommandJson the
  flag goes through, so a hand-edited or corrupt marker degrades to the
  env/default command rather than injecting a bogus argv into a build.

Because this is persistent state, add/update logs one line when the command
comes from the pin, naming .spm-injected.json, so a stale pin is diagnosable
from build output instead of invisible. There is no "clear" verb short of
`deinit`, as with the version pin.

Also corrects two comments asserting that the build-time sync reads
`readArtifactsVersionOverride`. It does not — that reader has no production
caller, so only the write half of the version pin is wired. Wiring it up is a
separate change; the comments are fixed here because they are actively
misleading.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 29, 2026
@chrfalch
chrfalch marked this pull request as draft July 29, 2026 17:26
@chrfalch
chrfalch marked this pull request as ready for review July 30, 2026 08:44
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Jul 30, 2026
@chrfalch chrfalch changed the title SPM: persist --config-command so the in-build sync keeps using it fix(swiftpm): persist --config-command so the in-build sync keeps using it Jul 30, 2026
@chrfalch
chrfalch requested a review from cipolleschi July 30, 2026 13:17
## Summary:

The `--config-command` flag has never been documented, and the pin that keeps
the in-build sync using it was added without a docs change. Cover both in
spm-scripts.md:

- a `--configCommand <json>` row in CLI Options, naming
  `RCT_SPM_AUTOLINKING_CONFIG_COMMAND` as the equivalent env var,
- a short section giving the resolution order (flag ->
  RCT_SPM_AUTOLINKING_CONFIG_COMMAND -> the `configCommand` pinned in
  `.spm-injected.json` -> the default `@react-native-community/cli config`) and
  why the pin has to exist: the Sync SPM Autolinking phase inherits neither the
  flag nor the shell that exported the env var, so an unpinned command turns a
  successful `add` into failing builds. Also states that `deinit` drops the
  marker and the pin with it,
- the marker's dual role in the "What to commit" table: reversal record *and*
  pinned configuration,
- a Troubleshooting row keyed on the symptom people will search for — the build
  phase failing with `@react-native-community/cli config` exiting non-zero.

Docs only; no behavior change. Deliberately not reformatted: this file is not
Prettier-formatted on this branch, and reformatting would bury the change.

## Changelog:

[Internal] - Document `spm --configCommand` and how the autolinking config
command is persisted

## Test Plan:

Docs only — nothing to run. Every statement was checked against the code on
this branch: the marker field name (`configCommand` in
`generate-spm-xcodeproj.js`), both input routes persisting
(`resolveConfigCommandToPin` = flag ?? env), the pin never shadowing the env
var (`resolveExplicitConfigCommand`), the actions that read it
(`needsCliConfig` covers add/update/sync/scaffold), and the failure being a
hard build error (config-command failure sets exit 2, which the generated build
phase turns into `exit 1`).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@meta-codesync

meta-codesync Bot commented Jul 31, 2026

Copy link
Copy Markdown

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D114317929.

@meta-codesync meta-codesync Bot closed this in ed3229a Jul 31, 2026
@meta-codesync meta-codesync Bot added the Merged This PR has been merged. label Jul 31, 2026
@meta-codesync

meta-codesync Bot commented Jul 31, 2026

Copy link
Copy Markdown

@cipolleschi merged this pull request in ed3229a.

fabriziocucci pushed a commit that referenced this pull request Aug 3, 2026
…ng it (#57756)

Summary:
**`spm add --config-command` worked once, then broke every build.**

An app that replaces `react-native-community/cli` autolinking — an Expo app, for instance — has to override the autolinking config command, which `--config-command` (and `RCT_SPM_AUTOLINKING_CONFIG_COMMAND`) exists to do. But the flag was never stored anywhere. So:

1. `npx react-native spm add --config-command '[...]'` → succeeds, writes a valid project ✅
2. Build in Xcode → the "Sync SPM Autolinking" phase re-derives `autolinking.json`, doesn't know about the flag, falls back to the default command, and fails ❌

```
PhaseScriptExecution failed with a nonzero exit code
  → Sync SPM Autolinking
  → 'npx --no-install react-native-community/cli config' exited with status 1
```

The only real workaround was exporting `RCT_SPM_AUTOLINKING_CONFIG_COMMAND` into Xcode's environment — i.e. committing it to `.xcode.env` — which shouldn't be necessary when you already passed a flag. Reported by the Expo team while testing SwiftPM.

**Fix:** pin the command into the `.spm-injected.json` marker at `add`/`update` time, and read it back on later runs — the same set-or-preserve pin the neighbouring `artifactsVersionOverride` already uses.

Resolution order, unchanged at the front and only extended at the back:

```
--config-command  →  RCT_SPM_AUTOLINKING_CONFIG_COMMAND  →  pinned value  →  default
```

**Both input routes persist.** The help text advertises the env var as an equivalent way to supply the command, so pinning only the flag would have left half the documented interface broken in exactly the same way — export the env var, run `spm add`, and the build phase (which does not inherit your shell) still fails. The pin therefore stores the *resolved* command from either route.

Two subtleties worth a reviewer's eye:

- `generateAutolinkingConfig` resolves the env var *internally* when no explicit command is passed, so handing it the pin would silently outrank a developer's env override. The read path therefore **withholds** the pin while the env var is set, letting the existing precedence do its job. The four order cases are tested, including that a whitespace-only env var falls through to the pin rather than stranding it.
- A pinned value is re-validated through the same `parseConfigCommandJson` the flag goes through, so a hand-edited or corrupt marker degrades to the env/default command instead of injecting a bogus argv into a build.

Because this is now persistent state, `add`/`update` logs one line when the command comes from the pin, naming `.spm-injected.json` — a stale pin should be diagnosable from build output rather than invisible. There is no "clear" verb short of `deinit`, same as the version pin; that is noted in the marker comment.

122 added lines across three source files. No new mechanism, no changes to the sync scripts, and nothing baked into the generated build phase.

**Noticed while here, filed separately, deliberately not fixed:** `readArtifactsVersionOverride` — the version pin this is modelled on — has **no production caller**. Only its write half is wired, and two comments claim the build-time sync reads it. Those comments are corrected here (they misled me while writing this); wiring the version pin up is its own change.

### This isn't blocking anyone

Expo's SwiftPM verification is **not blocked** on this, so it needn't be rushed. The env-var half of the override already works at build time: adding

```sh
export RCT_SPM_AUTOLINKING_CONFIG_COMMAND='["node","…/expo-modules-autolinking.js","react-native-config","--json","--platform","ios"]'
```

to the app's `.xcode.env` (or `.xcode.env.local`) gets the command into the sync phase, because the generated phase sources both files before dispatching. That is what unblocks Expo today, and it is exactly the "commit an env var to `.xcode.env`" step this PR removes the need for.

One caveat that argues for fixing it properly rather than documenting the workaround: the phase sources `.xcode.env` **only when `NODE_BINARY` is unset** (`nodeAndRnDirPreamble`). An app that sets `NODE_BINARY` as an Xcode build setting — a documented RN practice — never sources those files, so the workaround silently does nothing there and the build fails with no hint as to why. Persisting the flag doesn't depend on any of that plumbing.

## Changelog:

[Internal] [Fixed] - SwiftPM: persist `spm --config-command` so the in-build autolinking sync keeps using it

Pull Request resolved: #57756

Test Plan:
`yarn jest packages/react-native/scripts` → **31 suites, 703 tests** (25 new).

Each new test written red first, covering:

- the command round-trips through `.spm-injected.json` (marker content asserted)
- `add` → `update` **without** the flag keeps the pin; a later flag overwrites it
- `add` with **only the env var** set pins the env-derived command, and a later run with neither flag nor env resolves it back
- all four resolution-order cases, including that **the env var beats the pin**, and that a whitespace-only env var pins nothing and falls through
- an invalid non-blank env var still fails loud rather than pinning garbage
- a corrupt or hand-edited pin (bare string, `[]`, non-string member, empty-string member, object) degrades to the default rather than throwing
- `deinit` drops it with the marker

Not covered: no test drives a real `sync` end to end, since that needs artifacts, codegen and a real pbxproj. The two halves are tested separately against the same marker field — the injector writes `configCommand`, and the resolver reads it. The original failure was reported from a real Expo app build; confirmation that this fixes that build is still pending on the Expo side.

Reviewed By: fabriziocucci

Differential Revision: D114317929

Pulled By: cipolleschi

fbshipit-source-id: a0fe47de3da55b25e320b000a2b0b1b44b88af9a
(cherry picked from commit ed3229a)
meta-codesync Bot pushed a commit that referenced this pull request Aug 10, 2026
Summary:
**`spm add --version <ver>` pinned a value that nothing ever read back.**

The marker write has been there all along, and so has the reader — `readArtifactsVersionOverride()` in `spm/generate-spm-xcodeproj.js`, exported and unit-tested. It just had **zero production callers**. Every reference to it was a test.

`determineVersion` — the only resolver — went straight from the flag to `package.json`:

```js
let version = args.version;      // --version
if (version == null) {
  version = pkgJson.version;     // react-native/package.json; marker never consulted
}
```

That value picks which artifact slots the project gets wired to. So:

1. `spm add --version 0.88.0-nightly-…` → wires the nightly's slots, pins the label ✅
2. `spm update` (no flag) → silently resolves `package.json`'s version instead, re-pointing the project at different slots, while the marker still claims the nightly ❌

`--version` was effectively single-use. In this monorepo `package.json` is `1000.0.0`, which has no published artifacts, so a flagless run after a pinned `add` fails outright — which is why the standing advice has been to pass `--version` on *every* invocation. That advice was working around this bug.

**Fix:** insert the pin between the two existing sources.

```
--version  →  pinned override  →  react-native/package.json
```

15 lines of logic. `spm download` and the scaffold path pick it up for free, since both consume the same resolved value. Because this is persistent state, one line is logged when the pin is the source, so a stale pin is diagnosable instead of silent; there is still no way to clear it short of `deinit`.

**Three comments were actively wrong** and are corrected here: the reader's doc block, the marker-field comment, and `findInjectedXcodeproj`'s comment all asserted that the build-time sync calls this via `readArtifactsVersionOverride`. It does not and never did — the `sync` action returns before artifacts are resolved at all. Those comments are what made the gap invisible; they misled me while investigating.

## Changelog:

[Internal] [Fixed] - SwiftPM: `spm --version` now sticks, so a later run without the flag keeps using the pinned artifact version

Pull Request resolved: #57762

Test Plan:
`yarn jest packages/react-native/scripts` → **31 suites, 684 tests**, all green.

New tests, written red first — the load-bearing one failed with `Expected: "0.80.0" / Received: "1000.0.0"`, i.e. exactly the reported bug:

- `--version` given → wins, even with a different value pinned
- no flag, pin present → the pinned version is used
- no flag, no pin → `package.json`'s version (unchanged behaviour)
- no flag, corrupt or absent marker → `package.json`'s version, no throw
- the log line fires only when the pin is the source

The three fallback cases passed *before* the fix too, which is the point — they pin today's behaviour so this change can't regress it.

## Note on landing order

Touches `setup-apple-spm.js` and `spm/generate-spm-xcodeproj.js`, which #57744, #57756 and #57757 also touch. All are cut independently from `main`; whichever lands first, I'll rebase the rest. #57756 is the closest relative — it does the same wiring for `--config-command`, which had the identical write-only-pin shape.

Reviewed By: fabriziocucci

Differential Revision: D114318107

Pulled By: cipolleschi

fbshipit-source-id: 157da5b2eaaef9adee924eaa1832b7a38b008f4c
meta-codesync Bot pushed a commit that referenced this pull request Aug 10, 2026
…es (#57757)

Summary:
**SwiftPM has no equivalent of CocoaPods' `script_phase`, so a framework that generates content at build time can't get one.** The first casualty is expo-constants: nothing writes `EXConstants.bundle/app.config`, which shows up at runtime as *"Unable to find the embedded app config"*.

This adds a 6th field to the SwiftPM autolinking plugin contract:

```js
scriptPhases: [{
  id: 'expo-constants.app-config',   // stable: ledger key + deterministic UUID seed
  name: 'Generate Expo app.config',  // Xcode's display name
  script: '…',
  position: 'end',                   // 'end' (default) | 'beforeCompile'
  inputPaths: ['$(SRCROOT)/../app.json'],
  outputPaths: ['$(TARGET_BUILD_DIR)/…/EXConstants.bundle/app.config'],
  alwaysOutOfDate: true,
}]
```

The plugin returns data; RN validates it, records it to a `.spm-plugin-script-phases.json` sidecar (written even when empty, so removing a plugin clears stale entries), and `spm add`/`update` emits one `PBXShellScriptBuildPhase` per entry — tracked in `.spm-injected.json` by `id`, so `update` reconciles and `deinit` reverts.

### Verified end to end by the Expo team

On a real Expo app, against a local cut of this branch. A `position: 'end'` phase lands last, after the JS bundle phase:

```
5. Resources
6. Bundle React Native code and images
7. [Expo Dev Launcher] Strip Local Network Keys for Release
8. Generate Expo app.config          ← last
```

`BUILD SUCCEEDED`, and `EXConstants.bundle/app.config` is written with `sdkVersion: 56.0.0` — precisely the value whose absence caused the original bug. Red baseline confirmed first: before the declaration, the same app built with `0 script phase(s)`, an empty sidecar, and no `EXConstants.bundle` at all. They also independently confirmed `deinit` leaves zero residue, `add` is idempotent (same sha1 twice), and no phase duplicates.

Their side is expo/expo#47647.

### Design decisions worth a reviewer's attention

- **`end` appends at the true end of `buildPhases`**, which is *after* the JS bundle phase — where expo-constants must write, since it targets `$TARGET_BUILD_DIR`. Anchoring relative to the Frameworks phase (the obvious-looking choice) lands it *before* the bundle phase, because real template order is `Sources, Frameworks, Resources, Bundle React Native code and images`.
- **`beforeCompile` anchors after RN's own "Sync SPM Autolinking" phase**, which must stay first since it regenerates autolinking — a plugin phase ahead of it would run against stale generated content. The anchor chains forward so declared order survives. Position and relative order are re-derived every sync, so a phase dragged by hand in Xcode returns to its declared slot.
- **Validation is fatal**, matching `flavoredFrameworks` rather than the lenient `watchPaths`. A silently dropped phase means the content is never written and the app fails at runtime with no build-time signal — which is the bug being fixed.
- **`id` is the ledger key and the UUID seed.** The charset allows a scoped npm name (`expo/log-box`) but excludes `:`, which separates the `plugin:<id>` seed. `__proto__`/`constructor`/`prototype` are rejected because `plainObject['__proto__'] = v` vanishes through `JSON.stringify`, which would record a phase that `deinit` could never remove.
- **A plugin-supplied `name` reaches pbxproj comments**, and those are scanned by single-line regexes. What lands in a comment is therefore normalized: a name containing `*/`, `{` or `,` otherwise produced a brace-unbalanced project Xcode couldn't open, or an orphan phase `deinit` reported removing but didn't. The full name still goes verbatim into the `name` field Xcode displays. The same normalization now covers generated-source filenames, which had the identical hole.

### Also fixed in passing

`add → update → deinit` did **not** restore `project.pbxproj` byte-for-byte, even with zero script phases: the second run's marker forgot what the first had created, leaving an empty `packageReferences` / `packageProductDependencies` and the generated `.xcscheme` behind. The created-record now carries forward and `scheme.created` is sticky. Two guards came with that, both tested: a created array field is removed only when it is **empty** after RN's own members come out (so a package a user added to it survives `deinit`), and the scheme is deleted only if it is still RN's own (so a scheme the user has taken over is left alone).

## Changelog:

[Internal] [Added] - SwiftPM: autolinking plugins can declare build-time script phases via `scriptPhases`

Pull Request resolved: #57757

Test Plan:
`yarn jest packages/react-native/scripts` → **853 tests**, all green. The SwiftPM suite specifically went from **462 → 637** tests.

Written red first throughout. Coverage includes:

- one declared phase → exactly one `PBXShellScriptBuildPhase`, correct `name`/`shellScript`/serialized paths; `alwaysOutOfDate` emitted as unquoted `1` only when set
- `end` lands last; `beforeCompile` lands after the sync phase and before Sources; declared order preserved for multiple phases of each position and for a mix; a changed `position` is re-seated on the next sync
- add / update-in-place / remove keyed on `id`; unchanged re-sync byte-identical; `deinit` byte-identical with no orphan object or section
- a 17-row hostile-`name` matrix (`{ } ( ) , ; = */ /* * /`, unbalanced quote, tab, unicode, 300 chars, a name that normalizes to empty) × {balanced after add, byte-identical re-inject, clean deinit}
- scripts containing quotes, backslashes, newlines and `$(VAR)` round-trip through emission, refresh and deinit
- contract validation: 16 malformed-entry cases, duplicate `id` across plugins, reserved ids, scoped ids accepted, `:` rejected
- `add → update → deinit` byte-identity with zero phases and with two

**Not covered by unit tests, deliberately:** that `end` runs after the JS bundle phase. The `plain-app.pbxproj` fixture has no bundle phase, so it is unassertable here — this is disclosed in a comment at the test rather than papered over, and is exactly what the Expo verification above establishes.

**Known limitation, not addressed here:** against a project Xcode has previously saved, `add → deinit → add` is structurally identical (same UUIDs, same reference counts) but not byte-identical — Xcode writes multi-line dicts in sorted order, the injector writes single-line dicts in insertion order, which shows up as formatting churn in a committed `project.pbxproj`. Pre-existing for every object the injector emits, not specific to script phases, and filed separately.

## Note on landing order

This touches `generate-spm-xcodeproj.js` and `spm-pbxproj.js`, which #57744 and #57756 also touch — including the same marker-write block. All three are cut independently from `main`; whichever lands first, I'll rebase the others. Happy to restack in whatever order is easiest to review.

Reviewed By: fabriziocucci

Differential Revision: D114318236

Pulled By: cipolleschi

fbshipit-source-id: 4aa7958c302323299eda9db17adcec0d86edeebe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants